#include "common/header.h"
#include "common/serialization.h"

namespace XGC
{
	namespace common
	{

		template< class type >
		serialization& serialization_in( serialization& stream, type v )	{ stream.putn( (xgc_byte*)&v, sizeof(v) ); return stream; }

		template< class type >
		serialization& serialization_out( serialization& stream, type &v )	{ stream.getn( (xgc_byte*)&v, sizeof(type) ); return stream; }

		serialization& operator << ( serialization& stream, bool c )			{ return serialization_in< bool >( stream, c ); }
		serialization& operator << ( serialization& stream, char c )			{ return serialization_in< char >( stream, c ); }
		serialization& operator << ( serialization& stream, short c )			{ return serialization_in< short >( stream, c ); }
		serialization& operator << ( serialization& stream, int c )				{ return serialization_in< int >( stream, c ); }
		serialization& operator << ( serialization& stream, long c )			{ return serialization_in< long >( stream, c ); }
		serialization& operator << ( serialization& stream, long long c )		{ return serialization_in< long long >( stream, c ); }
		serialization& operator << ( serialization& stream, unsigned char c )	{ return serialization_in< unsigned char >( stream, c ); }
		serialization& operator << ( serialization& stream, unsigned short c )	{ return serialization_in< unsigned short >( stream, c ); }
		serialization& operator << ( serialization& stream, unsigned int c )	{ return serialization_in< unsigned int >( stream, c ); }
		serialization& operator << ( serialization& stream, unsigned long c )	{ return serialization_in< unsigned long >( stream, c ); }
		serialization& operator << ( serialization& stream, unsigned long long c ){ return serialization_in< unsigned long long >( stream, c ); }
		serialization& operator << ( serialization& stream, float c )			{ return serialization_in< float >( stream, c ); }
		serialization& operator << ( serialization& stream, double c )			{ return serialization_in< double >( stream, c ); }
		serialization& operator << ( serialization& stream, long double c )		{ return serialization_in< long double >( stream, c ); }
		serialization& operator << ( serialization& stream, const std::string &c )
		{
			stream.putn( (xgc_byte*)c.c_str(), c.length()+1 );
			return stream;
		}

		serialization& operator << ( serialization& stream, const std::wstring &c )
		{
			stream.putn( (xgc_byte*)c.c_str(), (c.length()<<1)+sizeof( wchar_t/*std::wstring::traits_type::char_type*/ ) );
			return stream;
		}

		serialization& operator << ( serialization& stream, const xgc_lpcstr c )
		{
			stream.putn( (xgc_byte*)c, strlen(c)+1 );
			return stream;
		}

		serialization& operator << ( serialization& stream, const xgc_lpcwstr c )
		{
			stream.putn( (xgc_byte*)c, (wcslen(c)+1)*sizeof(wchar_t) );
			return stream;
		}

		//serialization& operator << ( serialization& stream, const buffer &c )
		//{
		//	size_t size = c.capacity();
		//	stream.putn( (char*)&size, sizeof(size_t) );
		//	stream.putn( (char*)c.base(), size );
		//	return stream;
		//}

		serialization& operator >> ( serialization& stream, bool &c )			{ return serialization_out< bool >( stream, c ); }
		serialization& operator >> ( serialization& stream, char &c )			{ return serialization_out< char >( stream, c ); }
		serialization& operator >> ( serialization& stream, short &c )			{ return serialization_out< short >( stream, c ); }
		serialization& operator >> ( serialization& stream, int &c )			{ return serialization_out< int >( stream, c ); }
		serialization& operator >> ( serialization& stream, long &c )			{ return serialization_out< long >( stream, c ); }
		serialization& operator >> ( serialization& stream, long long &c )		{ return serialization_out< long long >( stream, c ); }
		serialization& operator >> ( serialization& stream, unsigned char &c )	{ return serialization_out< unsigned char >( stream, c ); }
		serialization& operator >> ( serialization& stream, unsigned short &c )	{ return serialization_out< unsigned short >( stream, c ); }
		serialization& operator >> ( serialization& stream, unsigned int &c )	{ return serialization_out< unsigned int >( stream, c ); }
		serialization& operator >> ( serialization& stream, unsigned long &c )	{ return serialization_out< unsigned long >( stream, c ); }
		serialization& operator >> ( serialization& stream, unsigned long long &c){ return serialization_out< unsigned long long >( stream, c ); }
		serialization& operator >> ( serialization& stream, float &c )			{ return serialization_out< float >( stream, c ); }
		serialization& operator >> ( serialization& stream, double &c )			{ return serialization_out< double >( stream, c ); }
		serialization& operator >> ( serialization& stream, long double &c )	{ return serialization_out< long double >( stream, c ); }
		serialization& operator >> ( serialization& stream, std::string &c )
		{
			c = (xgc_lpcstr)stream.rd_ptr();
			stream.seekoff( c.length()+1, serialization::cur, serialization::out );
			return stream;
		}

		serialization& operator >> ( serialization& stream, std::wstring &c )
		{
			c = (xgc_lpcwstr)stream.rd_ptr();
			stream.seekoff( (c.length()<<1)+sizeof(wchar_t), serialization::cur, serialization::out );
			return stream;
		}

		serialization& operator >> ( serialization& stream, xgc_lpcstr &c )
		{
			c = (xgc_lpcstr)stream.rd_ptr();
			stream.seekoff( strlen(c)+1, serialization::cur, serialization::out );
			return stream;
		}

		serialization& operator >> ( serialization& stream, xgc_lpcwstr &c )
		{
			c = (xgc_lpcwstr)stream.rd_ptr();
			stream.seekoff( (wcslen(c)<<1)+sizeof(wchar_t), serialization::cur, serialization::out );
			return stream;
		}
		
		//serialization& operator >> ( serialization& stream, buffer &c )
		//{
		//	size_t size;
		//	stream.getn( &size, sizeof(size_t) );
		//	if( size > c.capacity() )
		//		throw( std::exception( "overflow", -1 ) );
		//	stream.getn( c.base(), size );
		//}
	}
}
//#include <set>
//#include <map>
//#include <queue>
//#include <deque>
//struct __ttt__
//{
//	int a;
//	int b;
//};
//
//serialization& operator << ( serialization& stream, const __ttt__& c )
//{
//	return stream << c.a << c.b;
//}
//
//serialization& operator >> ( serialization& stream, __ttt__& c )
//{
//	return stream >> c.a >> c.b;
//}
//
//void do_bufstream_test()
//{
//	serialization buf( 1024 );
//	int n[11] = {1,2,3,4,5,6,7,8,9,0,1};
//	buf << 1 << 0.5f << 43l << short(558);
//	buf << "1234656";
//
//	buf << serialization( (char*)n, sizeof(n), serialization::in, sizeof(n) );
//
//	std::vector< int > vec_in, vec_out;
//	std::list<int> list_in, list_out;
//	std::deque<int> deque_in, deque_out;
//	std::set<int> set_in, set_out;
//	std::map<int, int> map_in, map_out;
//
//	std::vector< __ttt__* > pvec_in, pvec_out;
//	std::list< __ttt__* >	plist_in, plist_out;
//	std::deque< __ttt__* >	pdeque_in, pdeque_out;
//	std::set< __ttt__* >	pset_in, pset_out;
//	std::map<int, __ttt__*>	pmap_in, pmap_out;
//	for( int i = 0; i < 10; ++i )
//	{
//		__ttt__ *p = new __ttt__;
//		p->a = 1 * i;
//		p->b = 2 * i;
//		vec_in.push_back(i);
//		pvec_in.push_back(p);
//
//		list_in.push_back(i);
//		plist_in.push_back(p);
//
//		deque_in.push_back(i);
//		pdeque_in.push_back(p);
//
//		set_in.insert(i);
//		pset_in.insert(p);
//
//		map_in.insert( std::make_pair( i, i ) );
//		pmap_in.insert( std::make_pair( i, p ) );
//	}
//	buf << vec_in << pvec_in;
//	buf << list_in << plist_in;
//	buf << deque_in << pdeque_in;
//	buf << set_in << pset_in;
//	buf << map_in << pmap_in;
//
//	int a;
//	float b;
//	long c;
//	short d;
//	std::string e;
//	int on[11];
//	buf >> a >> b >> c >> d >> e;
//	buf >> serialization( (const char*)on, sizeof(on) );
//	buf >> vec_out >> pvec_out 
//		>> list_out >> plist_out
//		>> deque_out >> pdeque_out
//		>> set_out >> pset_out
//		>> map_out >> pmap_out;
//}
